#ifndef __SVMTRAIN_H__
#define __SVMTRAIN_H__

/// Includes cuda
#include <cutil_math.h>
/// Includes projects
#include "..\common\framework.h"
#include "Cache.h"
#include "svmTrainData.h"
#include "svmTrainConfig.h"

class svmTrain {
public:
	svmTrain(svmTrainConfig*,svmTrainData*);
	template<MultiLabel method, KernelType type> void train();
	void printModel();
	void cleanTrainingResult();

	int blockWidth;
	float* alpha;
	float* rho;
	Cache_C* gpuCache;
private:
	float *devResult;
	float* hostResult;

	//float* devData;
	float* devTransposedData;
	//size_t devDataPitch;
	size_t devTransposedDataPitch;
	//int devDataPitchInFloats;
	int devTransposedDataPitchInFloats;
	float* devLabels;
	float* devLabelsInUse;
	size_t devLabelsPitch;
	int devLabelsPitchInFloats;
	float* devKernelDiag;
	float* devSelfDot;
	float* devAlphaPointer;
	float* devAlphaInUse;
	size_t devAlphaPitch;
	int devAlphaPitchInFloats;
	float* devF;
	float* devLocalFsRL;
	float* devLocalFsRH;
	int* devLocalIndicesRL;
	int* devLocalIndicesRH;
	int* devLocalIndicesMaxObj;
	float* devLocalObjsMaxObj;
	int2* devEllData;
	int* devEllRowLen;
	size_t devEllDataPitch;

	dim3 threads, blocks;
	int iLowCacheIndex, iHighCacheIndex;
	bool iLowCompute, iHighCompute;

	svmTrainConfig * config;
	svmTrainData * trainingData;

	template<MultiLabel method, KernelType type> void allocate();
	template<MultiLabel method, KernelType type> void preCompute();
	void initTraining();
	void firstStep(int, int);
	template<KernelType type> void firstOrderSMO(float,int,float,int);
	template<MultiLabel method, KernelType type> void release();
	inline int firstOrderShareSize();
	void dummy();
};

#endif
